from SPARQLWrapper import SPARQLWrapper, JSON

"""
@ivar category: This is the list of categories associated with a term
@ivar term: This is the term that we are grabbing categories out from  
"""
class CategoryGrabber(object):
    sparqlConn = SPARQLWrapper("http://dbpedia.org/sparql");
    
    def __init__(self):
        self.category = set([]);
        self.term = "";
    """ @summary: This is part of CategoryGrabbers API. This is the method that we call
                  to start the process of grabbing categories from dbPedia
       @param term: This is the term (ngram, or something else) that we want to find categories for 
    """ 
    def grab(self, term):
        self.term = term;
        query = self.__buildCatQuery(self.term, None);
        resultSet = self.__runQuery(query);
        if( len(resultSet) == 0):
            #Check for disambiguates
            resultSet = self.__tryDisambiguates(term);
            self.__tryRedirect(resultSet);
        else:
            self.__foundCategories(resultSet);
    
    def hasCategory(self, category):
        return category in self.category;
    
    #@summary: This is part of CategoryGrabbers API. Clears the category list of its categories.
    def clear(self):
        self.category = set([]);
    
    def __foundCategories(self, resultSet):
        for result in resultSet:
            self.category.add((result["subject"]["value"])[37:]);
    
    def __foundRedirURIs(self, resultSet):
        for result in resultSet:
            newURI = result["redirect"]["value"];
        return newURI;
    
    def __redirect(self, newURI):
            query = self.__buildCatQuery(None, newURI);
            return self.__runQuery(query);
     
    def __tryDisambiguates(self, term):
        query = self.__buildDisambQuery(term);
        resultSet = self.__runQuery(query);
        if(len(resultSet) > 0):
            for result in resultSet:
                q = self.__buildCatQuery(None, result["disamb"]["value"]);
                resSet = self.__runQuery(q);
                self.__foundCategories(resSet);
            
    def __tryRedirect(self, resultSet, ):
        query = self.__buildRetQuery(self.term);
        resultSet = self.__runQuery(query);
        if(len(resultSet) == 1):
            newURI = self.__foundRedirURIs(resultSet);
            resultSet = self.__redirect(newURI);
            if(len(resultSet) > 0):
                self.__foundCategories(resultSet);
            #else: Then there is nothing to find....
        #else: print("We are unable to find what you are looking for. [ "+self.term+" ]");
    
    def __runQuery(self, query):   
        CategoryGrabber.sparqlConn.setQuery(query);
        CategoryGrabber.sparqlConn.setReturnFormat(JSON);
        resultSet = CategoryGrabber.sparqlConn.query().convert();
        return resultSet["results"]["bindings"];
      
    def __buildCatQuery(self, term = None, newURI = None):
        if((term is not None) and (newURI is None)):
            query =("PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> "
                    "SELECT ?subject "
                    "WHERE { <http://dbpedia.org/resource/"+ term +"> skos:subject ?subject }");
            return query;
        elif((term is None) and (newURI is not None)):
            query = ("PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> "
                     "SELECT ?subject "
                     "WHERE { <"+ newURI +"> skos:subject ?subject }");
            return query;
        else:
            return 0;       
    
    def __buildDisambQuery(self, term):
        query = ("PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> "
                 "SELECT ?disamb "
                 "WHERE { <http://dbpedia.org/resource/"+ term +"> dbpprop:disambiguates ?disamb }");
        return query;
    
    #@summary: Creates the redirect query 
    def __buildRetQuery(self, term):
            query = ("PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> "
                     "SELECT ?redirect "
                     "WHERE { <http://dbpedia.org/resource/"+ term +"> dbpprop:redirect ?redirect }");
            return query;